<?php

class CDbConnection
{
    public $dbc;

    static $PDO_OPTIONS = array(
        PDO::ATTR_CASE              => PDO::CASE_LOWER,
        PDO::ATTR_ERRMODE           => PDO::ERRMODE_EXCEPTION,
        PDO::ATTR_ORACLE_NULLS      => PDO::NULL_NATURAL,
        PDO::ATTR_STRINGIFY_FETCHES => false
    );

    public function __construct($connection_url)
    {
        $info = self::parse($connection_url);

        $host[] = "host=$info->host";
        if(!empty($info->port))
            $host[] = "port=$info->port";
        if(!empty($info->db))
            $host[] = "dbname=$info->db";

        try{
            $this->dbc = new PDO($info->scheme. ':'. implode(';', $host), $info->user, $info->pass, static::$PDO_OPTIONS);
        }catch(PDOException $e){
            exit($e);
        }
    }

    public static function parse($connection_url)
    {
        $url = @parse_url($connection_url);

        if(!isset($url['host']))
            throw new CDbException('Database host must be specified in the connection string.');

        $info = new stdClass();
        $info->scheme   = $url['scheme'];
        $info->host     = $url['host'];
        $info->db       = isset($url['path']) ? substr($url['path'], 1) : null;
        $info->user     = isset($url['user']) ? $url['user'] : null;
        $info->pass     = isset($url['pass']) ? $url['pass'] : null;
        $info->port     = isset($url['port']) ? $url['port'] : null;

        return $info;
    }

    public function exec($sql)
    {
        return $this->dbc->exec($sql);
    }

    public function query($sql, $values=array())
    {
        try{
            if(!($sth = $this->dbc->prepare($sql)))
                throw new CDbException('set');
        }catch(PDOException $e){
            exit($e);
        }

        $sth->setFetchMode(PDO::FETCH_ASSOC);

        try{
            if(!$sth->execute($values))
                throw new CDbException($this);
        }catch(PDOException $e){
            throw new CDbException($this);
        }
        return $sth;
    }

    public function fetchOne($sql)
    {
        $sth = $this->query($sql);
        $row = $sth->fetch(PDO::FETCH_NUM);
        return $row[0];
    }

    public function fetchRow($sql)
    {
        $sth = $this->query($sql);
        return $sth->fetch(PDO::FETCH_ASSOC);
    }

    public function fetchAll($sql)
    {
        $sth = $this->query($sql);
        return $sth->fetchAll(PDO::FETCH_ASSOC);
    }
}

